package com.njtoyo.taxi.admin.service.business.geo.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.baomidou.mybatisplus.extension.conditions.update.LambdaUpdateChainWrapper;
import com.njtoyo.taxi.admin.aop.YDException;
import com.njtoyo.taxi.admin.cache.PrimaryCachePutter;
import com.njtoyo.taxi.admin.library.Const;
import com.njtoyo.taxi.admin.library.common.util.CopyUtil;
import com.njtoyo.taxi.admin.logic.geo.DriverRegionAreaLogic;
import com.njtoyo.taxi.admin.mapper.master.entity.*;
import com.njtoyo.taxi.admin.mapper.master.mapper.*;
import com.njtoyo.taxi.admin.rest.presenter.business.geo.AllListPresenter;
import com.njtoyo.taxi.admin.rest.presenter.business.geo.RegionListPresenter;
import com.njtoyo.taxi.admin.rest.presenter.platfrom.AdminUserIdentityPresenter;
import com.njtoyo.taxi.admin.rest.wrapper.business.canton.*;
import com.njtoyo.taxi.admin.service.business.geo.GeoDriverRegionService;
import com.taxi.entity.common.RestResult;
import com.njtoyo.taxi.entity.backend.AdminUser;
import com.njtoyo.taxi.entity.backend.Enum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ModelAttribute;

import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Component
@DS(Const.PRIMARY_DS)
public class GeoDriverRegionServiceImpl implements GeoDriverRegionService {

    @Autowired
    private GeoDriverRegionMapper geoDriverRegionMapper;

    @Autowired
    private GeoDriverRegionAreaMapper geoDriverRegionAreaMapper;

    @Autowired
    private DriverRegionAreaLogic driverRegionAreaLogic;
    @Autowired
    private GeoDriverRegionOpenMapper geoDriverRegionOpenMapper;
    @Autowired
    private PrimaryCachePutter primaryCachePutter;
    @Autowired
    private RegionCallRelationMapper regionCallRelationMapper;

    @Override
    public RestResult<List<AllListPresenter>> getAll(@ModelAttribute("admin") AdminUser adminUser) {
        AdminUserIdentityPresenter identity = (AdminUserIdentityPresenter) adminUser.getIdentity();

        List<GeoDriverRegion> list = new LambdaQueryChainWrapper<>(geoDriverRegionMapper)
                .in(!adminUser.getAccountType().equals(Enum.AccountType.platform), GeoDriverRegion::getId, identity.getDriverRegionIds())
                .select(GeoDriverRegion::getId, GeoDriverRegion::getName)
                .list();

        List<AllListPresenter> res = CopyUtil.copyList(list, AllListPresenter.class);
        return RestResult.success(res);
    }

    @Override
    @Transactional
    public RestResult create(RegionCreateWrapper wrapper) {
        // 校验是否已经存在area_id
        Boolean checkAreaIdsExist = this.checkAreaIdsExist(null, wrapper.getAreaIds());
        if (checkAreaIdsExist) {
            return RestResult.failed("地区已被行政区引用，请检查所选择的地区");
        }

        // geo_driver_region
        GeoDriverRegion region = new GeoDriverRegion();
        region.setName(wrapper.getName());
        geoDriverRegionMapper.insert(region);

        Long regionId = region.getId();

        // geo_driver_region_area
        List<RegionAreaCreateWrapper> list = new ArrayList<>();
        for (Long areaId : wrapper.getAreaIds()) {
            RegionAreaCreateWrapper item = new RegionAreaCreateWrapper();
            item.setRegionId(regionId);
            item.setAreaId(areaId);
            list.add(item);
        }

        geoDriverRegionAreaMapper.createBatch(list);
        primaryCachePutter.deleteDriverRegion();
        primaryCachePutter.deleteAllArea();

        return RestResult.success();
    }

    @Override
    public RestResult<IPage<RegionListPresenter>> getList(RegionQueryWrapper wrapper) {
        IPage<RegionListPresenter> res = geoDriverRegionMapper.getListByPage(wrapper);

        List<Long> cantonIds = res.getRecords().stream().map(RegionListPresenter::getId).collect(Collectors.toList());
        if (!cantonIds.isEmpty()) {
            List<AllListPresenter> areaList = geoDriverRegionMapper.getListByCantonIds(cantonIds);
            for (RegionListPresenter region : res.getRecords()) {
                List<AllListPresenter> itemAreaList = new ArrayList<>();
                for (AllListPresenter area : areaList) {
                    if (region.getId().equals(area.getRegionId())) {
                        itemAreaList.add(area);
                    }
                }
                region.setAreaList(itemAreaList);
                GeoDriverRegionOpen open = geoDriverRegionOpenMapper.selectOne(Wrappers.<GeoDriverRegionOpen>lambdaQuery()
                        .eq(GeoDriverRegionOpen::getDriverRegionId, region.getId()));
                if (ObjectUtil.isNull(open)) {
                    region.setType("close");
                } else {
                    region.setType("open");
                }
            }
        }

        return RestResult.success(res);
    }

    @Override
    public RestResult<Boolean> update(Long id, RegionUpdateWrapper wrapper) {
        // 校验是否已经存在area_id
        Boolean checkAreaIdsExist = this.checkAreaIdsExist(id, wrapper.getAreaIds());
        if (checkAreaIdsExist) {
            return RestResult.failed("地区已被行政区引用，请检查所选择的地区");
        }

        // geo_driver_region
        new LambdaUpdateChainWrapper<>(geoDriverRegionMapper)
                .eq(GeoDriverRegion::getId, id)
                .set(Objects.nonNull(wrapper.getName()), GeoDriverRegion::getName, wrapper.getName())
                .update();

        // geo_driver_region_area
        if (!wrapper.getAreaIds().isEmpty()) {
            // 删除原有areaIds
            QueryWrapper<GeoDriverRegionArea> deleteArea = new QueryWrapper<>();
            deleteArea.eq("driver_region_id", id);
            geoDriverRegionAreaMapper.delete(deleteArea);

            // 写入新的areaIds
            driverRegionAreaLogic.createInsert(id, wrapper.getAreaIds());
            primaryCachePutter.deleteDriverRegion();
            primaryCachePutter.deleteAllArea();
        }

        return RestResult.success();
    }

    @Override
    public RestResult<Boolean> updateState(Long id, RegionUpdateWrapper wrapper) {
        if ("open".equals(wrapper.getType())) {
            GeoDriverRegionOpen open = geoDriverRegionOpenMapper.selectOne(Wrappers.<GeoDriverRegionOpen>lambdaQuery()
                    .eq(GeoDriverRegionOpen::getDriverRegionId, id));
            if (ObjectUtil.isNull(open)) {
                GeoDriverRegionOpen addOpen = new GeoDriverRegionOpen();
                addOpen.setDriverRegionId(id);
                geoDriverRegionOpenMapper.insert(addOpen);
            }
        } else {
            geoDriverRegionOpenMapper.delete(Wrappers.<GeoDriverRegionOpen>lambdaQuery()
                    .eq(GeoDriverRegionOpen::getDriverRegionId, id));
        }
        primaryCachePutter.deleteDriverRegion();
        primaryCachePutter.deleteAllArea();
        return RestResult.success();
    }

    @Override
    public RestResult getRegionByAreaId(Long areaId) {
        GeoDriverRegion driverRegion = driverRegionAreaLogic.getRegionByAreaId(areaId);
        return RestResult.success(driverRegion);
    }

    // 校验是否已经存在area_id
    private Boolean checkAreaIdsExist(Long regionId, List<Long> areaIds) {
        if (areaIds.isEmpty()) {
            return true;
        }

        Integer areaCheckCount = new LambdaQueryChainWrapper<>(geoDriverRegionAreaMapper)
                .in(GeoDriverRegionArea::getAreaId, areaIds)
                .ne(Objects.nonNull(regionId), GeoDriverRegionArea::getDriverRegionId, regionId)
                .count();

        return areaCheckCount > 0;
    }


    @Override
    public RestResult getOrderSet(Long driverRegionId) {
        List<RegionCallRelation> regionCallRelations = regionCallRelationMapper.selectList(Wrappers
                .<RegionCallRelation>lambdaQuery()
                .eq(RegionCallRelation::getDriverRegionId, driverRegionId));
        List<Dict> res = new ArrayList<>();
        if (ObjectUtil.isNotNull(regionCallRelations)) {
            Map<Long, List<RegionCallRelation>> groupModel = regionCallRelations.stream().collect(Collectors.groupingBy(RegionCallRelation::getVehicleTypeId));

            for (Map.Entry<Long, List<RegionCallRelation>> entry : groupModel.entrySet()) {
                Dict dict = new Dict();
                List<RegionCallRelation> list = entry.getValue();
                List<Long> callTypeIds = list.stream().map(RegionCallRelation::getCallTypeId).collect(Collectors.toList());
                dict.put("vehicleModelId", entry.getKey());
                dict.put("callTypeIds", callTypeIds);
                res.add(dict);
            }
        }
        return RestResult.success(res);
    }



    @Override
    @Transactional(rollbackOn = Exception.class)
    public RestResult orderSet(DriverOrderSetWrapper wrapper) {
        // 先删除原有配置
        try {
            regionCallRelationMapper.delete(Wrappers.<RegionCallRelation>lambdaQuery()
                    .eq(RegionCallRelation::getDriverRegionId, wrapper.getDriverRegionId()));
        } catch (Exception e) {
            throw new YDException("清除原有配置失败");
        }
        List<RegionCallRelation> relationsToInsert = new ArrayList<>();
        // 处理每条规则
        for (DriverOrderSetWrapper.Rule rule : wrapper.getRules()) {
            // 规则级校验
            if (rule.getVehicleModelId() == null) {
                return RestResult.failed("车型ID不能为空");
            }

            // 处理每个接单类型
            for (Long callTypeId : rule.getCallTypeIds()) {
                if (callTypeId == null) {
                    return RestResult.failed("接单类型不能为空");
                }

                RegionCallRelation relation = new RegionCallRelation();
                relation.setDriverRegionId(wrapper.getDriverRegionId());
                relation.setCallTypeId(callTypeId);
                relation.setVehicleTypeId(rule.getVehicleModelId());
                relationsToInsert.add(relation);
            }
        }

        // 6. 批量插入新配置
        if (!relationsToInsert.isEmpty()) {
            try {
                regionCallRelationMapper.batchInsert(relationsToInsert);
            } catch (Exception e) {
                throw new YDException("保存接单配置失败");
            }
        }

        return RestResult.success();
    }
}
